﻿using AutoMapper;
using Common.Library;
using Container.Library;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using Network.Library;
using Swashbuckle.AspNetCore.Filters;
using Swashbuckle.AspNetCore.Swagger;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Validate.Library;

namespace Api.MallManage
{
    /// <summary>
    /// Startup配置文件
    /// </summary>
    public static class StartupConfigure
    {

        /// <summary>
        /// 将服务添加到容器
        /// </summary>
        /// <param name="services"></param>
        /// <param name="Configuration"></param>
        /// <param name="_IWebHostEnvironment"></param>
        public static void AdminConfigureServices(this IServiceCollection services, IConfiguration Configuration, IHostingEnvironment _IWebHostEnvironment)
        {

            #region HttpContextHelper
            //注册HttpContextHelper类型服务
            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            #endregion

            #region 跨域配置
            //配置跨域处理
            services.AddCors(options =>
            {
                options.AddPolicy("AllowSpecificOrigin", builder =>
                {
                    builder
                    .SetIsOriginAllowed(origin => true)
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowCredentials();
                });
            });
            #endregion

            #region AutoMapper
            //AutoMapper初始化
            services.AddAutoMapper(MappingContainer.GetProfileTypes());
            #endregion

            #region Swagger

            services.AddSwaggerGen(options =>
            {
                options.DescribeAllEnumsAsStrings();

                var swaggerInfo = ConfigHelper<List<Dictionary<string, object>>>.InitConfig("Config/swagger.config.json");
                var swaggerConfig = swaggerInfo.GetNodeInfo("SwaggerConfig");
                foreach (var item in swaggerConfig)
                {
                    options.SwaggerDoc(item["SwaggerDoc"].ToString(), new Info
                    {
                        Version = Configuration.GetSection("SwaggerDoc:Version").Value,
                        Title = Configuration.GetSection("SwaggerDoc:Title").Value,
                        Description = Configuration.GetSection("SwaggerDoc:Description").Value
                    });
                }

                Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.xml").ToList().ForEach(file =>
                {
                    options.IncludeXmlComments(file, true);
                });
                options.DocumentFilter<HiddenApiFilter>(); // 在接口类、方法标记属性 [HiddenApi]，可以阻止【Swagger文档】生成
                options.OperationFilter<AddResponseHeadersFilter>();
                //options.OperationFilter<SwaggerFileUploadFilter>();

                var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } }, };
                options.AddSecurityRequirement(security);
                options.AddSecurityDefinition("Bearer", new ApiKeyScheme
                {
                    Description = "Format: Bearer {auth_token}",
                    Name = "Authorization",
                    In = "header"
                });
            });
            #endregion

            #region Jwt token 身份验证

            var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
            var signingKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes("NR0wigNB4ZzAq5OGqHgFAV8hfH5vhVwoNub2"));
            services.Configure<JwtIssuerOptions>(options =>
            {
                options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
                options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
                options.SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha384);
            });

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

            }).AddJwtBearer(configureOptions =>
            {
                configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
                configureOptions.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,//控制在令牌期间是否验证颁发者
                    ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],//获取或设置表示将使用的有效颁发者的System.String检查令牌的颁发者。
                    ValidateAudience = true,//控制在标记期间是否验证访问群体验证。
                    ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],

                    ValidateIssuerSigningKey = true,//控制是否验证Microsoft.IdentityModel.Tokens.SecurityKey签名的securityToken被调用
                    IssuerSigningKey = signingKey,

                    RequireExpirationTime = false,//指示令牌是否必须是否具有“过期”值
                    ValidateLifetime = true,//控制是否在令牌期间验证生存期
                    ClockSkew = TimeSpan.Zero//获取或设置验证时间时要应用的时钟偏移。
                    //注意这是缓冲过期时间，总的有效时间等于这个时间加上jwt的过期时间，如果不配置，默认是5分钟
                };
                configureOptions.SaveToken = true;
            });
            #endregion

            #region JWT授权注入
            //JWT授权注入
            services.AddSingleton<IJwtFactory, JwtFactory>();
            #endregion

        }

        /// <summary>
        /// 配置http请求管道
        /// </summary>
        /// <param name="app"></param>
        /// <param name="env"></param>
        /// <param name="loggerFactory"></param>
        /// <param name="applicationLifetime"></param>
        public static void AdminConfigure(this IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IApplicationLifetime applicationLifetime)
        {

            #region HttpContextAccessor
            //将对象 IHttpContextAccessor 注入HttpContextHelper静态对象中             
            HttpContextHelper.Configure(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>());
            #endregion

            #region 使用跨域
            //使用跨域
            app.UseCors("AllowSpecificOrigin");
            #endregion

            #region AutoMapper
            //AutoMapper
            MappingContainer.RegisterMappings();
            #endregion

            //ASP.NET Core 使用app.UseStaticFiles配置静态文件中间件，达到类似IIS中虚拟目录的效果，可访问位于 Web 根目录之外的文件
            app.UseStaticFiles();

            //使用异常记录页面
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            #region Swagger

            //启用中间件服务生成Swagger作为JSON终结点
            app.UseSwagger();

            //启用中间件服务对swagger-ui，指定Swagger JSON终结点
            app.UseSwaggerUI(options =>
            {
                var swaggerInfo = ConfigHelper<List<Dictionary<string, object>>>.InitConfig("Config/swagger.config.json");
                var swaggerConfig = swaggerInfo.GetNodeInfo("SwaggerConfig");
                foreach (var item in swaggerConfig)
                {
                    options.SwaggerEndpoint(item["JsonPath"].ToString(), item["Title"].ToString());
                }

                options.RoutePrefix = string.Empty;// "swagger";//这里主要是不需要再输入swagger这个默认前缀
                options.DefaultModelsExpandDepth(-1);//隐藏掉实体映射
            });

            #endregion

        }
    }
}
